from schedule import every, repeat
import logging


class baseUnit:  # 基础单位
    def __init__(
        self,
        name: str,
        info: str,
        actions: list[str] = None,
        amount: int = 1,
        check_str: str = None,
    ) -> None:
        """
        初始化

        参数:
        -------
            name (str): 单位名称
            info (str): 单位描述
            actions (list): 单位事件
            amount (int): 单位数量
        """
        if actions is None:
            actions = []
        self.name = name
        self.info = f"    {info}"
        self.actions_dict = {}  # 事件字典 {action:func}
        self.amount = amount
        if check_str:
            self.check_str = check_str
        else:
            self.check_str = self.info
        for action in actions:
            self.actions_dict[action] = None
        self.actions_dict['check'] = self.check

    def __str__(self):
        return self.name

    def bind(self, action: str, func):
        """
        连接事件到函数

        参数:
        -------
            action (str): 事件
            func (function): 对应函数
        """
        self.actions_dict[action] = func

    def execute(self, action: str, args: dict = None):
        """
        执行事件对应的函数
        此处return的值为func的返回值
        流程为：
            1. server调用execute找到对应func
            2. execute无参数调用func，若返回值为字典(requirements)，则在返回的列表中标注为“需求值”，
               若返回值为其他类型，则标注为“正常”。
            3. 若server传入了参数，就将该参数传递给func，返回结果标注“正常”

        参数:
        -------
            action (str): 事件
            args (dict) : 参数，格式为{"名称":值}
        """
        func = self.actions_dict[action]
        if args:
            return ["normal", func(args)]
        returns = func()
        if type(returns) is dict:
            return ["requirements", returns]
        else:
            return ["normal", returns]

    def getAmount(self):
        return self.amount

    def getInfo(self):
        return self.info

    def getActions(self):
        return list(self.actions_dict.keys())

    def setCheck(self, string):
        self.check_str = string

    def check(self):
        return [(200, self.check_str)]


class ItemUnit(baseUnit):
    def __init__(
        self,
        item,
        name: str,
        info: str,
        amount: int = 1,
        check_str: str = "",
        actions: list[str] = None,
        pickable: bool = False,
        infinity: bool = False,
    ) -> None:
        """
        初始化

        参数:
        -------
            name (str): 物品名称
            info (str): 物品描述
            actions (list[str]): 物品事件
            item (item.baseItem): 物品对应item
            pickable (bool, 可选): 是否可拾取，默认为False
            infinity (bool, 可选): 数量是否无限，默认为False
        """
        if actions is None:
            actions = []
        self.actions_dict["pick_up"] = self.pickUp
        super().__init__(name, info, actions, amount, check_str)
        self.pickable = pickable
        self.infinity = infinity
        self.item = item

    def pickUp(self):
        """
        拾取
        若该物品不为无穷个，则将个数减少一个
        返回该物品所对应的item

        Returns
        -------
        None/item
            item -> 物品
        """
        if not self.pickable:
            return [(200, "这玩意似乎捡不起来")]
        if not self.infinity:
            if self.amount != 0:
                self.amount -= 1
            else:
                return [(200, "似乎没什么能捡起来的了")]
        return self.item


class IncrementalUnit(baseUnit):
    def __init__(
        self,
        name: str,
        info: str,
        actions: list[str] = None,
        amount: int = 1,
        check_str: str = None,
        delay: int = 1,
        step: int = 1,
        maximums: int = 1,
    ):
        super().__init__(name, info, actions, amount, check_str)
        self.delay = delay
        self.step = step
        self.maximums = maximums

        @repeat(every(self.delay).seconds)
        def increase():
            result = self.amount + self.step
            if result <= self.maximums:
                self.amount = result
            else:
                self.amount = self.maximums
            logging.debug(f"{self}已将数量增加至{self.amount}")
